﻿/****************************************************************************
**  @copyright  TinKinG
**  @contract   lsnbing@126.com
**
**  @author TinKinG
**  @date   2020-3-12
**
**
*****************************************************************************/

#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QDebug>

#include "PerspectiveView.h"

PerspectiveView::PerspectiveView(QWidget *parent) : QWidget(parent)
{

}

Mat PerspectiveView::PerspectiveTrans(Mat src, Point2f* scrPoints, Point2f* dstPoints)
{
    Mat dst;
    Mat Trans = getPerspectiveTransform(scrPoints, dstPoints);
#ifdef Q_OS_WIN
    warpPerspective(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
#else
    warpPerspective(src, dst, Trans, Size(src.cols, src.rows), INTER_CUBIC);
#endif
    return dst;
}

cv::Mat PerspectiveView::getMatFromImage(const QImage &image)
{
    cv::Mat mat;
    switch (image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
#ifdef Q_OS_WIN
        cv::cvtColor(mat, mat, CV_BGR2RGB);
#else
        cv::cvtColor(mat, mat, COLOR_BGR2RGB);
#endif
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}

QImage PerspectiveView::getImageFromMat(const cv::Mat &mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return QImage();
    }
}

QRectF PerspectiveView::getRect(const QPointF &p)
{
    QRectF rect(p.x() - m_radius,p.y() - m_radius,2 * m_radius,2 * m_radius);
    return rect;
}

void PerspectiveView::mouseMoveEvent(QMouseEvent *ev)
{
    qDebug() << ev->pos();
}

void PerspectiveView::paintEvent(QPaintEvent *event)
{
    QPainter main(this);
    main.setRenderHint(QPainter::Antialiasing);

    QPainter p(&m_bkgImg);
    p.setRenderHint(QPainter::Antialiasing);

    m_bkgImg.fill(0);

    p.drawImage(QRect(0,0,1024,1024),m_mainImg);
    p.drawImage(QRect(0,0,1024,1024),getImageFromMat(m_dstMat));

    main.drawRect(this->rect());
    main.drawImage(0,0,m_bkgImg);

//    p.setPen(Qt::blue);
//    p.setBrush(Qt::blue);

//    p.drawRoundedRect(getRect(p1),m_radius,m_radius);
//    p.drawRoundedRect(getRect(p2),m_radius,m_radius);
//    p.drawRoundedRect(getRect(p3),m_radius,m_radius);
//    p.drawRoundedRect(getRect(p4),m_radius,m_radius);
}

void PerspectiveView::setMainImg(const QImage &img)
{
    m_mainImg = img;
    m_bkgImg = QImage(img.width(),img.height(),QImage::Format_ARGB32);
    if (img.size().width() != 1024 || img.size().height() != 1024) {
        qDebug() << "error";
        exit(0);
    }
    resize(m_mainImg.size());
    update();
}

void PerspectiveView::setTopImg(const QImage &img)
{
    m_topImg = img;

    p1 = QPointF(0,0);
    p2 = QPointF(0,m_topImg.size().height());
    p3 = QPointF(m_topImg.size().width(),m_topImg.size().height());
    p4 = QPointF(m_topImg.size().width(),0);

    m_srcMat = getMatFromImage(m_topImg);
    qDebug() << m_srcMat.rows << m_srcMat.cols;

    Point2f AffinePoints0[4] = { Point2f(p1.x(), p1.y()), Point2f(p2.x(), p2.y()),
                                 Point2f(p3.x(), p3.y()), Point2f(p4.x(), p4.y()) };

    float topX = 0.25;
    float top = 70;

    float bottomX = 0.21;
    float bottom = p2.y() * 0.62;
    Point2f AffinePoints1[4] = { Point2f(m_topImg.width() * topX, top),
                                 Point2f(m_topImg.width() * bottomX,bottom ),Point2f(m_topImg.width() * (1-bottomX), bottom),
                                 Point2f(m_topImg.width() * (1-topX), top) };

    //    Mat dst_affine = AffineTrans(I, AffinePoints0, AffinePoints1);
    m_dstMat = PerspectiveTrans(m_srcMat, AffinePoints0, AffinePoints1);

    update();
}

QImage PerspectiveView::getImage() const
{
    return m_bkgImg;
}

